package com.small.nacos.core.distributed.distro.task.execute;

import com.small.nacos.core.distributed.distro.component.DistroComponentHolder;
import com.small.nacos.core.distributed.distro.entity.DistroData;
import com.small.nacos.core.distributed.distro.entity.DistroKey;
import com.small.nacos.naming.consistency.DataOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Author zhoujin
 * @Date 2022/11/13 16:10
 */
public class DistroSyncChangeTask extends AbstractDistroExecuteTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(DistroSyncChangeTask.class);

    private final DistroComponentHolder distroComponentHolder;

    public DistroSyncChangeTask(DistroKey distroKey, DistroComponentHolder distroComponentHolder) {
        super(distroKey);
        this.distroComponentHolder = distroComponentHolder;
    }

    @Override
    public void run() {
        LOGGER.info("[DISTRO-START] {}", toString());
        try {
            String type = getDistroKey().getResourceType();
            DistroData distroData = distroComponentHolder.findDataStorage(type).getDistroData(getDistroKey());
            distroData.setType(DataOperation.CHANGE);
            Boolean result = distroComponentHolder.findTransportAgent(type).syncData(distroData, getDistroKey().getTargetServer());
            if (!result) {
                handleFailedTask();
            }
            LOGGER.info("[DISTRO-END] {} result: {}", toString(), result);
        } catch (Exception e) {
            LOGGER.warn("[DISTRO] Sync data change failed.", e);
            handleFailedTask();
        }
    }

    /**
     * 重新执行失败的任务
     *
     * @return
     */
    private void handleFailedTask() {
        String type = getDistroKey().getResourceType();
        DistroData distroData = distroComponentHolder.findDataStorage(type).getDistroData(getDistroKey());
        DistroKey distroKey = distroData.getDistroKey();
        distroComponentHolder.findFailedTaskHandler(type).retry(distroKey, DataOperation.CHANGE);
    }
}
